// Package shunfeng 顺丰快递路由查询
package shunfeng

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	uuid "github.com/satori/go.uuid"
	"io/ioutil"
	"net/http"
	"net/url"
	"orderApi/express"
	"strconv"
	"time"
)

// SfRoutesPost 顺丰快递路由查询               partnerID 合作伙伴编码（即顾客编码）         timestamp 调用接口时间戳          secret合作伙伴密钥                trackingNumber 快递单号
func SfRoutesPost(partnerID, secret, trackingNumber string) (benXiRoutes express.BenXiRoutes) {
	benXiRoutes.Status = true
	routesPostUrl := "https://bspgw.sf-express.com/std/service"
	// 访问令牌，使用OAuth2方式认证时必填	获取方法参考：OAuth2认证说明
	accessTokens, err := accessToken(partnerID, secret)
	if err != nil {
		benXiRoutes.Status = false
		benXiRoutes.Message = fmt.Sprintf("%v", err)
		return benXiRoutes
	}
	access := new(SfRoutingReceive)
	json.Unmarshal(accessTokens, access)

	if access.ApiResultCode == "A1011" {
		benXiRoutes.Status = false
		benXiRoutes.Message = "accessToken访问令牌获取失败,Code :A1011, 描述:" + access.ApiErrorMsg
		return benXiRoutes
	}

	// 请求参数 <msgData>
	msg := new(SfRoutingRequest)
	msg.Language = 0
	msg.TrackingType = 1
	number := make([]string, 1)
	number[0] = trackingNumber
	msg.TrackingNumber = number
	msgData, _ := json.Marshal(msg)

	// 时间戳
	timestamp := time.Now().UnixNano() / 1e6

	// 公共请求参数
	values := url.Values{}
	values.Add("partnerID", partnerID)                               // 合作伙伴编码（即顾客编码）
	values.Add("requestID", fmt.Sprintf("%x", uuid.NewV4().Bytes())) // 请求唯一号UUID
	values.Add("serviceCode", "EXP_RECE_SEARCH_ROUTES")              // 接口服务代码（EXP_RECE_SEARCH_ROUTES）
	values.Add("timestamp", strconv.FormatInt(timestamp, 10))        // 调用接口时间戳
	// values.Add("msgDigest", "")                         // 数字签名,使用数字签名方式认证时必填	签名方法参考：数字签名认证说明
	values.Add("accessToken", access.AccessToken) // 访问令牌，使用OAuth2方式认证时必填	获取方法参考：OAuth2认证说明
	values.Add("msgData", string(msgData))        // 业务数据报文

	// Http Post 请求数据
	form, err := http.PostForm(routesPostUrl, values)
	if err != nil {
		benXiRoutes.Status = false
		benXiRoutes.Message = fmt.Sprintf("%v", err)
		return benXiRoutes
	}

	defer form.Body.Close()
	all, _ := ioutil.ReadAll(form.Body)

	// 开始json 序列化
	sfMsgData := new(SfRoutingReceive)
	json.Unmarshal(all, sfMsgData)
	sfRoutingReceiveData := new(SfRoutingReceiveData) // 这个参数 本身是一个 String  json
	json.Unmarshal([]byte(sfMsgData.ApiResultData), sfRoutingReceiveData)

	// 因为在返回客户数据 和进行存储的时候，需要统一格式，所以在使用 xml 进行序列化 从而达到两个不同的结构体变量可以进行数据的传输   （还没有找到其他办法---其实可以使用for 进行循环赋值 但是效率不高）
	marshal, _ := xml.Marshal(sfRoutingReceiveData.MsgData.RouteResps[0])
	xml.Unmarshal(marshal, &benXiRoutes)

	return benXiRoutes
}

// accessToken 访问令牌，使用OAuth2方式认证时必填	获取方法参考：OAuth2认证说明
func accessToken(partnerID, secret string) ([]byte, error) {
	// 拼接请求的Url
	accessTokenUrl := "https://sfapi.sf-express.com/oauth2/accessToken?partnerID=" + partnerID + "&grantType=password&secret=" + secret
	// 公共请求参数
	values := url.Values{}
	values.Add("Content-type", "application/x-www-form-urlencoded;charset=UTF-8")

	form, err := http.PostForm(accessTokenUrl, values)
	if err != nil {
		return nil, err
	}

	defer form.Body.Close()
	all, _ := ioutil.ReadAll(form.Body)

	return all, nil
}
